package org.zpmis.api.business;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.stereotype.Service;
import org.zpmis.common.base.AdminLoginUser;
import org.zpmis.common.base.AppletsLoginUser;
import org.zpmis.common.base.BaseWebService;
import org.zpmis.common.exception.BusinessException;
import org.zpmis.common.result.ResultCode;
import org.zpmis.common.utils.StringUtil;
import org.zpmis.domain.file.service.FileService;
import org.zpmis.domain.invoice.model.Invoice;
import org.zpmis.domain.invoice.qo.*;
import org.zpmis.domain.invoice.service.InvoiceService;
import org.zpmis.domain.invoice.vo.InvoiceListVo;
import org.zpmis.domain.mail.enums.MailEnum;
import org.zpmis.domain.mail.model.TemplateMailMessageParam;
import org.zpmis.domain.mail.service.MailService;
import org.zpmis.domain.order.model.Order;
import org.zpmis.domain.order.service.OrderService;
import tk.mybatis.mapper.entity.Condition;
import tk.mybatis.mapper.entity.Example;

import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * Created with CodeGenerator
 * Description: 发票业务处理
 * @author  Yang
 * Date: 2021-7-26
 * Time: 14:58:56
 */
@Service
@Slf4j
public class InvoiceWebService extends BaseWebService {
     @Reference
     private InvoiceService invoiceService;

     @Reference
     private MailService mailService;

     @Reference
     private FileService fileService;

     @Reference
     private OrderService orderService;


    /**
     * 申请开发票
     * @param applyInvoiceQo
     * @throws BusinessException
     * @throws Exception
     */
    public void applyInvoice(ApplyInvoiceQo applyInvoiceQo) throws BusinessException,Exception {
        //获取当前登录用户的用户信息
        AppletsLoginUser appletsLoginUser = super.getAppletsLoginUser();
        if(appletsLoginUser == null){
            throw new BusinessException(ResultCode.USER_NOT_LOGIN);
        }
        Long businessId = applyInvoiceQo.getBusinessId();
        Integer businessType = applyInvoiceQo.getBusinessType();
        if(businessType == null){
            businessType = 1;
        }
        //防止重复申请
        Condition condition = new Condition(Invoice.class);
        condition.createCriteria()
                .andEqualTo("isDeleted",0)
                .andEqualTo("businessId",businessId)
                .andEqualTo("businessType",businessType)
                .andNotEqualTo("status",2);
        List<Invoice> invoiceList = invoiceService.findByCondition(condition);
        if(!invoiceList.isEmpty()){
            throw new BusinessException(ResultCode.INVOICE_APPLY_ERROR);
        }

        Invoice invoice = Invoice.builder()
                .businessId(businessId)
                .businessType(businessType)
                .invoiceAmount(StringUtil.isEmpty(applyInvoiceQo.getInvoiceAmount())? BigDecimal.ZERO: new BigDecimal(applyInvoiceQo.getInvoiceAmount()).setScale(2))
                .invoiceType(applyInvoiceQo.getInvoiceType())
                .openInvoiceType(applyInvoiceQo.getOpenInvoiceType())
                .invoiceCompanyName(applyInvoiceQo.getInvoiceCompanyName())
                .invoiceTaxpayerIdentiNumber(applyInvoiceQo.getInvoiceTaxpayerIdentiNumber())
                .bankName(applyInvoiceQo.getBankName())
                .bankAccountName(applyInvoiceQo.getBankAccountName())
                .bankAccount(applyInvoiceQo.getBankAccount())
                .invoiceAddress(applyInvoiceQo.getInvoiceAddress())
                .invoiceMobile(applyInvoiceQo.getInvoiceMobile())
                .createId(appletsLoginUser.getId())
                .createPerson(appletsLoginUser.getName())
                .createTime(Instant.now().toEpochMilli())
                .status(0)
                .isDeleted(0)
                .deliveryAdress(applyInvoiceQo.getDeliveryAdress())
                .consignee(applyInvoiceQo.getConsignee())
                .deliveryMobile(applyInvoiceQo.getDeliveryMobile())
                .email(applyInvoiceQo.getEmail())
                .build();

        invoiceService.save(invoice);
    }

    /**
     * 发票列表查询
     * @param invoiceListQo
     * @return
     * @throws BusinessException
     * @throws Exception
     */
    public PageInfo invoiceList(InvoiceListQo invoiceListQo)  throws BusinessException,Exception{
        Integer businessType = invoiceListQo.getBusinessType();
        Integer invoiceType = invoiceListQo.getInvoiceType();
        Integer openInvoiceType = invoiceListQo.getOpenInvoiceType();
        String invoiceCompanyName = invoiceListQo.getInvoiceCompanyName();
        String invoiceTaxpayerIdentiNumber = invoiceListQo.getInvoiceTaxpayerIdentiNumber();
        String invoiceMobile = invoiceListQo.getInvoiceMobile();
        Integer status = invoiceListQo.getStatus();
        Long startTime = invoiceListQo.getStartTime();
        Long endTime = invoiceListQo.getEndTime();

        Condition condition = new Condition(Invoice.class);
        Example.Criteria criteria = condition.createCriteria();
        criteria.andEqualTo("isDeleted",0);

        if(businessType != null){
            criteria.andEqualTo("businessType",businessType);
        }
        if(invoiceType != null){
            criteria.andEqualTo("invoiceType",invoiceType);
        }
        if(openInvoiceType != null){
            criteria.andEqualTo("openInvoiceType",openInvoiceType);
        }
        if(status != null){
            criteria.andEqualTo("status",status);
        }
        if(StringUtil.isNotEmpty(invoiceCompanyName)){
            criteria.andLike("invoiceCompanyName","%"+invoiceCompanyName+"%");
        }
        if(StringUtil.isNotEmpty(invoiceTaxpayerIdentiNumber)){
            criteria.andLike("invoiceTaxpayerIdentiNumber","%"+invoiceTaxpayerIdentiNumber+"%");
        }
        if(StringUtil.isNotEmpty(invoiceMobile)){
            criteria.andLike("invoiceMobile","%"+invoiceMobile+"%");
        }
        if(startTime != null && endTime != null){
            criteria.andGreaterThanOrEqualTo("createTime",startTime);
            criteria.andLessThanOrEqualTo("createTime",endTime);
        }
        if(startTime != null && endTime == null){
            criteria.andGreaterThanOrEqualTo("createTime",startTime);
            criteria.andLessThanOrEqualTo("createTime",Instant.now().toEpochMilli());
        }
        if(startTime == null && endTime != null){
            criteria.andLessThanOrEqualTo("createTime",endTime);
        }
        condition.orderBy("createTime").desc();
        PageHelper.startPage(invoiceListQo.getPageNum(),invoiceListQo.getPageSize());
        List<Invoice> invoiceList = invoiceService.findByCondition(condition);
        PageInfo invoicePageInfo = new PageInfo<>(invoiceList);
        List<InvoiceListVo> resultList = invoiceList.stream().map(InvoiceListVo::new).collect(Collectors.toList());
        invoicePageInfo.setList(resultList);
        return invoicePageInfo;
    }

    /**
     * 审核发票信息
     * @param auditInvoiceQo
     * @throws BusinessException
     * @throws Exception
     */
    public void auditInvoice(AuditInvoiceQo auditInvoiceQo) throws BusinessException,Exception{
        AdminLoginUser adminLoginUser = super.getAdminLoginUser();
        if(adminLoginUser == null){
            throw new BusinessException(ResultCode.USER_NOT_LOGIN);
        }
        Long id = auditInvoiceQo.getId();
        Integer status = auditInvoiceQo.getStatus();
        String logisticsNum = auditInvoiceQo.getLogisticsNum();
        String invoiceAttachment = auditInvoiceQo.getInvoiceAttachment();
        String attachmentName = auditInvoiceQo.getAttachmentName();
        String remark = auditInvoiceQo.getRemark();
        Invoice invoice = invoiceService.findById(id);
        if(invoice == null){
            throw new BusinessException(ResultCode.DATA_NOT_FOUND);
        }
        //审核通过，纸质 必须输入物流单号，电子必须上传附件
        if(status == 1){
            if(invoice.getInvoiceType() == 1 && StringUtil.isEmpty(logisticsNum)){
                throw new BusinessException(ResultCode.INVOICE_LOGISTICSNUM_ERROR);
            }else if(invoice.getInvoiceType() == 2 && (StringUtil.isEmpty(invoiceAttachment) || StringUtil.isEmpty(attachmentName))){
                throw new BusinessException(ResultCode.INVOICE_ATTACHMENT_ERROR);
            }
        }
        invoiceService.update(
            Invoice.builder()
                    .id(id)
                    .status(status)
                    .logisticsNum(logisticsNum)
                    .attachmentName(attachmentName)
                    .invoiceAttachment(invoiceAttachment)
                    .auditTime(Instant.now().toEpochMilli())
                    .remark(remark)
                    .build()
        );
    }

    /**
     * 获取最近的一条发票信息
     * @param checkInvoiceQo
     * @return
     * @throws BusinessException
     * @throws Exception
     */
    public InvoiceListVo findRecentlyInvoice(CheckInvoiceQo checkInvoiceQo) throws BusinessException,Exception{
        Long businessId = checkInvoiceQo.getBusinessId();
        Integer businessType = checkInvoiceQo.getBusinessType();
        //获取最近的一条申请开票信息
        Condition condition = new Condition(Invoice.class);
        condition.createCriteria()
                .andEqualTo("isDeleted",0)
                .andEqualTo("businessId",businessId)
                .andEqualTo("businessType",businessType);
        condition.orderBy("createTime").desc();
        List<Invoice> invoiceList = invoiceService.findByCondition(condition);
        if(!invoiceList.isEmpty()){
            InvoiceListVo invoiceListVo = invoiceList.stream().map(InvoiceListVo::new).findFirst().get();
            return invoiceListVo;
        }
        return null;
    }

    /**
     * 发送发票邮件
     * @param sendInvoiceEmailQo
     * @return
     * @throws BusinessException
     * @throws Exception
     */
    public boolean sendInvoiceEmail(SendInvoiceEmailQo sendInvoiceEmailQo) throws BusinessException,Exception{
        Long id = sendInvoiceEmailQo.getId();
        String email = sendInvoiceEmailQo.getEmail();
        Invoice invoice = invoiceService.findById(id);
        Order order = orderService.findById(invoice.getBusinessId());
        if(invoice == null || order == null){
            throw new BusinessException(ResultCode.DATA_NOT_FOUND);
        }
        if(invoice.getStatus() != 1){
            throw new BusinessException(ResultCode.INVOICE_NOT_AUDIT);
        }
        String attachmentName = invoice.getAttachmentName();
        if(StringUtil.isEmpty(attachmentName)){
            throw new BusinessException(ResultCode.INVOICE_ATTACHMENT_EMPTY);
        }
        String[] attachNames = attachmentName.split(",");
        //附件参数 key是文件名 value是附件字节
        Map<String, byte[]> bytesMap = new HashMap<>();
        for (String attachName : attachNames) {
            try {
                byte[] bytes = fileService.getFileBytes(attachName);
                if(bytes != null){
                    bytesMap.put(attachName,bytes);
                }
            } catch (Exception e) {
                log.error("[sendInvoiceEmail]---exception:",e);
                throw new BusinessException(ResultCode.INVOICE_GET_ATTACHMENT_ERROR);
            }
        }
        //模板参数 对应每个邮件模板中的参数名保持一致
        Map<String, String> templateMap = new HashMap<>();
        templateMap.put("orderNumber",order.getOrderNumber());
        templateMap.put("invoiceDate", LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        boolean isSend = mailService.sendTemplateMail(new TemplateMailMessageParam(email, MailEnum.INVOICE, templateMap, bytesMap));
        return isSend;
    }
}
